#
#  --------------------------------------------------------------------------
#   Gurux Ltd
#
#
#
#  Filename: $HeadURL$
#
#  Version: $Revision$,
#                   $Date$
#                   $Author$
#
#  Copyright (c) Gurux Ltd
#
# ---------------------------------------------------------------------------
#
#   DESCRIPTION
#
#  This file is a part of Gurux Device Framework.
#
#  Gurux Device Framework is Open Source software; you can redistribute it
#  and/or modify it under the terms of the GNU General Public License
#  as published by the Free Software Foundation; version 2 of the License.
#  Gurux Device Framework is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#  See the GNU General Public License for more details.
#
#  More information of Gurux products: http://www.gurux.org
#
#  This code is licensed under the GNU General Public License v2.
#  Full text may be retrieved at http://www.gnu.org/licenses/gpl-2.0.txt
# ---------------------------------------------------------------------------

import sys
import traceback
import time
from gurux_common.io import Parity, StopBits, BaudRate
from gurux_serial import GXSerial
from gurux_net import GXNet
from gurux_dlms.enums import ObjectType
from gurux_dlms.objects import GXDLMSObject, GXDLMSClock, GXDLMSData, GXDLMSProfileGeneric
from GXSettings import GXSettings
from GXDLMSReader import GXDLMSReader

lnCodeMap = { \
    #Current, I-R
    "1,0,31,7,0,255" : "P2-1-1-1-0",\
    #Current, I-Y	
    "1,0,51,7,0,255" : "P2-1-2-1-0",\
    #Current, I-B	
    "1,0,71,7,0,255" : "P2-1-3-1-0",\
    #Voltage, R-N	
    "1,0,32,7,0,255" : "P1-2-1-1-0",\
    #Voltage, Y-N	
    "1,0,52,7,0,255" : "P1-2-2-1-0",\
    #Voltage, B-N	
    "1,0,72,7,0,255" : "P1-2-3-1-0",\
    #Voltage, R-Y	
    "1,0,32,7,0,255" : "P1-2-1-1-0",\
    #Voltage, B-Y	
    "1,0,52,7,0,255" : "P1-2-2-1-0",\
    #Signed power factor, R-phase	
    "1,0,33,7,0,255" : "P4-1-1-0-0",\
    #Signed power factor, Y-phase	
    "1,0,53,7,0,255" : "P4-2-1-0-0",\
    #Signed power factor, B-phase	
    "1,0,73,7,0,255" : "P4-3-1-0-0",\
    #Three phase power factor, PF	
    "1,0,13,7,0,255" : "P4-4-1-0-0",\
    #Frequency	
    "1,0,14,7,0,255" : "P9-1-0-0-0",\
    #Apparent power, kVA	
    "1,0,9,7,0,255" : "P3-4-4-1-0",\
    #Signed active power, kW	
    "1,0,1,7,0,255" : "P3-2-4-1-0",\
    #Signed reactive power, kvar	
    "1,0,3,7,0,255" : "P3-3-4-1-0",\
    #Cumulative energy, kWh	
    "1,0,1,8,0,255" : "P7-1-18-2-0",\
    #Cumulative energy, kvarh (Lag)	
    "1,0,5,8,0,255" : "P7-2-19-0-0",\
    #Cumulative energy, kvarh (Lead)	
    "1,0,8,8,0,255" : "P7-2-20-0-0",\
    #Cumulative energy, kVAh	
    "1,0,9,8,0,255" : "P7-3-18-0-0",\
    #Block energy, in kWh    
    "1,0,1,29,0,255" : "P7-1-18-2-0",\
    #Block energy, kvarh (lag)   
    "1,0,5,29,0,255" : "P7-2-19-0-0",\
    #Block energy, in kvarh (lead)   
    "1,0,8,29,0,255" : "P7-2-20-0-0",\
    #Block energy, in kVAh   
    "1,0,9,29,0,255" : "P7-3-18-0-0",\
}

def showD1(d1):
    print("show D1 values:")
    for it in d1:
        print("flag: %s\tvalue: %s" % (it[0], it[1]))
    print("\n")

def showDn(dn):
    lnList = dn[0]
    valList = dn[1]
    scalerMap = dn[2]

    for i in range(len(valList)):
        print("row %d :" % i)

        for j in range(len(lnList)):
            ln = lnList[j]
            val = valList[i][j]
            if isinstance(val, str) or isinstance(val, int):
                val = str(val)
            else:
                val = str(type(val))

            if ln in scalerMap:
                print("ln: %s\tvalue: %s\tscaler: %d\tunit: %d" % (ln, val, scalerMap[ln][0], scalerMap[ln][1]))
            else:
                print("ln: %s\tvalue: %s\tscaler: None\tunit: None" % (ln, val))

#Number of power-failures.	0, 0, 96, 7, 0, 255	-
#Cumulative power-failure duration	0, 0, 94, 91, 8, 255	-
#Cumulative tamper count	0, 0, 94, 91, 0, 255	-
#Cumulative billing count	0, 0, 0, 1, 0, 255	-
#Cumulative programming count	0, 0, 96, 2, 0, 255	-
#Billing date	0, 0, 0, 1, 2, 255	-
#Maximum demand, kW	1, 0, 1, 6, 0, 255	-
#Maximum demand, kVA	1, 0, 9, 6, 0, 255	-
#Cumulative energy, kWh (Import)	1, 0, 1, 8, 0, 255	有歧义
#Cumulative energy, kWh (Export)	1, 0, 2, 8, 0, 255	有歧义
#Cumulative energy, kVAh (Import)	1, 0, 9, 8, 0, 255	有歧义
#Cumulative energy, kVAh (Export)	1, 0, 10, 8, 0, 255	有歧义

def readDataObjValue(reader, ln):
    obj = GXDLMSData(ln)
    val = reader.read(obj, 2)
    if not isinstance(val, str) and isinstance(val, int):
        print("ln: %s, type: %s" % (ln, type(val)))
    else:
        val = str(val)
        print(val)
    
    if val is None:
        return ""
    else:
        return val

def readCaptureValues(reader, ln):
    obj = GXDLMSProfileGeneric(ln)
    reader.read(obj, 3)
    reader.read(obj, 2)

    lnList = []
    for it in obj.captureObjects:
        lnList.append(it[0].logicalName)

    return (lnList, obj.buffer)

def readScalerMap(reader, ln):
    scalerDict = {}
    obj = GXDLMSProfileGeneric(ln)
    reader.read(obj, 3)
    if len(obj.captureObjects) == 0:
        return scalerDict
    reader.read(obj, 2)
    if len(obj.captureObjects) != len(obj.buffer[0]):
        print("capture objects cnt: %d" % len(obj.captureObjects))
        print("buffer len: %d" % len(obj.buffer[0]))
        raise Exception("capture objects cnt with buffer len not match!")
    for k,v in zip(obj.captureObjects, obj.buffer[0]):
        scalerDict[k[0].logicalName] = v 
    return scalerDict

class SnapObject:
    def __init__(self, ln):
        self.ln = ln
        self.val = None
        self.unit = None

    def show():
        print("ln: %s" % self.ln)
        print("val type: %s" % type(self.val))
        if isinstance(self.val, int) or isinstance(self.val, str):
            print(self.val)
        else:
            print("val is None")
        if self.unit:
            print(self.unit)
        else:
            print("val is None")

#pylint: disable=too-few-public-methods,broad-except
class sampleclient():
    @classmethod
    def main(cls, args):
        # args: the command line arguments
        reader = None
        settings = GXSettings()
        try:
            # //////////////////////////////////////
            #  Handle command line parameters.
            ret = settings.getParameters(args)
            if ret != 0:
                return
            # //////////////////////////////////////
            #  Initialize connection settings.
        #    if isinstance(settings.media, GXSerial):
        #        if settings.iec:
        #            settings.media.baudrate = BaudRate.BAUD_RATE_300
        #            settings.media.bytesize = 7
        #            settings.media.parity = Parity.EVEN
        #            settings.media.stopbits = StopBits.ONE
        #        else:
        #            settings.media.baudrate = BaudRate.BAUD_RATE_9600
        #            settings.media.bytesize = 8 settings.media.parity = Parity.NONE settings.media.stopbits = StopBits.ONE
        #    elif not isinstance(settings.media, GXNet):
        #        raise Exception("Unknown media type.")

            # //////////////////////////////////////
            xmlHead = "<CDF><UTILITYTYPE CODE='1'>\n"
            xmlTail = "<AUTHENTICATOR></AUTHENTICATOR>\n</UTILITYTYPE></CDF>\n"
            
            reader = GXDLMSReader(settings.client, settings.media, settings.trace, settings.dtu)
            reader.initializeConnection()

            print("read D1 objects value...")
            xmlD1 = "\t<D1>\n"

            # read D1 ... 
            d1 = []

            #G1
            #ln  = "0.0.96.1.0.255"
            #val = readDataObjValue(reader, ln)
            #val = val.strip()
            #d1.append(("G1", val))

            ## G2
            #obj = GXDLMSClock()
            #val = reader.read(obj, 2)
            #val = str(val.value)
            #if len(val) == 19:
            #    tm = val[8:10] + "-" + val[5:7] + "-" + val[0:4] + val[10:]
            #    d1.append(("G2", tm))
            ## G3,G4
            #tm = time.strftime('%d-%m-%Y %H:%M:%S',time.localtime(time.time()))
            #d1.append(("G3", tm))
            #d1.append(("G4", tm))
            ## G7
            #ln = "1.0.0.4.3.255"
            #val = readDataObjValue(reader, ln)
            #d1.append(("G7", val))
            ## G8
            #ln = "1.0.0.4.2.255"
            #val = readDataObjValue(reader, ln)
            #d1.append(("G8", val))
            ## G15
            #ln = "0.0.94.91.9.255"
            #val = readDataObjValue(reader, ln)
            #d1.append(("G15", val))
            ## G22
            #ln = "0.0.96.1.1.255"
            #val = readDataObjValue(reader, ln)
            #d1.append(("G22", val))
            #print("read D1 objects done.")
            #
            #showD1(d1)
            
            #read D2 ...
#            print("read d2 ...")
#            ln = "1.0.94.91.0.255"
#            val = readCaptureValues(reader, ln)
#            d2CaptureObjects = val[0]
#            d2CaptureValues = val[1]
#
#            if len(d2CaptureObjects) != len(d2CaptureValues[0]):
#                raise Exception("d2 capture objects cnt not match val cnt!")
#
#            ln = "1.0.94.91.3.255"
#            d2ScalerMap = readScalerMap(reader, ln)
#
#            d2 = (d2CaptureObjects, d2CaptureValues, d2ScalerMap)
#            showDn(d2)
#            print("read d2 done.")

            ## read D3 ...
            ## read D4 ...
            print("read d4 ...")
            ln = "1.0.99.1.0.255"
            val = readCaptureValues(reader, ln)
            d4CaptureObjects = val[0]
            d4CaptureValues = val[1]
            if len(d4CaptureObjects) != len(d4CaptureValues[0]):
                raise Exception("d4 capture objects cnt not match val cnt!")

            ln = "1.0.94.91.4.255"
            d4ScalerMap = readScalerMap(reader, ln)

            d4 = (d4CaptureObjects, d4CaptureValues, d4ScalerMap)
            showDn(d4)
            print("read d4 done.")

            ## read D5 ...
            #ln = "1.0.94.91.7.255"
            #eventsScalerMap = readScaler(reader, ln, "eventsScaler")

            #ln = "0.0.99.98.0.255"
            #eventsLog0 = readProfileGeneric(reader, ln, "eventsLog0")
            #ln = "0.0.99.98.1.255"
            #eventsLog1 = readProfileGeneric(reader, ln, "eventsLog1")
            #ln = "0.0.99.98.2.255"
            #eventsLog2 = readProfileGeneric(reader, ln, "eventsLog2")
            #ln = "0.0.99.98.3.255"
            #eventsLog3 = readProfileGeneric(reader, ln, "eventsLog3")
            #ln = "0.0.99.98.4.255"
            #eventsLog4 = readProfileGeneric(reader, ln, "eventsLog4")
            #ln = "0.0.99.98.5.255"
            #eventsLog5 = readProfileGeneric(reader, ln, "eventsLog5")
            #ln = "0.0.99.98.6.255"
            #eventsLog6 = readProfileGeneric(reader, ln, "eventsLog6")

        except Exception:
            traceback.print_exc()
        finally:
            if reader:
                try:
                    reader.close()
                except Exception:
                    traceback.print_exc()
            print("Ended. Press any key to continue.")

if __name__ == '__main__':
    sampleclient.main(sys.argv)

